package org.example.user.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.example.commonapi.domain.Practice;
import org.example.commonapi.domain.R;
import org.example.commonapi.domain.User;
import org.example.commonapi.dto.InfoFormDTO;
import org.example.commonapi.dto.LoginInfo;
import org.example.commonapi.dto.StudentDto;
import org.example.commonapi.util.JwtUtil;
import org.example.commonapi.util.StringUtil;
import org.example.commonapi.util.options.InboxService;
import org.example.commonapi.util.oss.OssService;
import org.example.commonapi.util.redis.RedisService;
import org.example.commonapi.util.redis.UserPrefix;
import org.example.commonapi.vo.PieVO;
import org.example.commonapi.vo.StudentVO;
import org.example.commonapi.vo.StudyHistoryVO;
import org.example.commonapi.vo.TagVO;
import org.example.user.service.UserService;
import org.example.user.utils.VerifyUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Objects;


/**
 * @author XieNoDesire
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private JwtUtil jwtUtil;


    @Resource
    private RedisService redisService;

    @Resource
    private OssService ossService;

    @Resource
    private InboxService inboxService;

    /**
     * 测试
     * @return
     */
    @GetMapping("/hello")
    public R hello(HttpServletRequest request) {
        return R.success(request.getHeader("token"));
    }


    /**
     * 登录
     * @param loginInfo
     * @return
     */
    @PostMapping("/login")
    public R login(@RequestBody LoginInfo loginInfo) {
//      获取用户名+密码
        String username=loginInfo.getUsername();
        String password=loginInfo.getPassword();
        log.info("当前登录用户为{}",username);
        if(StringUtil.isAnyEmpty(username,password))return R.error("用户名或密码不能为空");
//      从数据库搜索
        User user =userService.login(username,password);
        if(user ==null)
            return R.error("用户名或密码错误");
        String token=setToken(user);
        return R.success(token);
    }

    /**
     * 注册
     * @param loginInfo
     * @return
     */
    @PostMapping("/register")
    public R register(@RequestBody LoginInfo loginInfo){
        //多参数判空
        if(StringUtil.isAnyEmpty(loginInfo.getUsername(),loginInfo.getPassword()))
            return R.error("用户名或密码不能为空");
        //用户已存在
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,loginInfo.getUsername());
        if(userService.exists(queryWrapper)) return R.error("用户名已存在");
        Long id=userService.register(loginInfo);
        loginInfo.setId(id);
        String token=setToken(new User(loginInfo));
        log.info("注册成功,当前注册用户为{}",loginInfo.getUsername());
        return R.success(token);
    }

    
    
    /**
     * 获取用户个人信息
     * @param request
     * @return
     */
    @GetMapping("/get")
    public R userinfo(HttpServletRequest request){
        //已登录
        LoginInfo loginInfo=jwtUtil.parseJwt(request.getHeader("token"));
        //从数据库搜索
        User user=userService.getById(loginInfo.getId());
        log.info("当前用户为{}",user);
        //todo 脱敏
        return R.success(user);
    }

    /**
     * 编辑用户信息
     * @param user 新用户信息
     * @return
     */
    @PutMapping("/update")
    public R updateUserInfo(@RequestBody User user,HttpServletRequest request){
        log.info("修改信息为{}",user);
        //如果用户名被修改，需要查看用户名是否重复，需要修改token
        if(StringUtil.isAnyEmpty(user.getUsername(),user.getPassword()))
            return R.error("用户名或密码不能为空");
        //修改登录信息
        LoginInfo loginInfo=new LoginInfo(user);
        boolean isUpdateLoginInfo=!loginInfo.equals(new LoginInfo(userService.getById(user.getId())));
        if(isUpdateLoginInfo){
            String token=setToken(user);
            log.info("修改登录信息成功，新token为{}",token);
        }
        //数据库修改
        userService.updateUserInfo(user,request);
        return R.success();
    }

    /**
     * 退出登录
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public R logout(HttpServletRequest request){
        LoginInfo loginInfo=jwtUtil.parseJwt(request.getHeader("token"));
        log.info("退出登录，退出的用户为{}",loginInfo);
        redisService.del(UserPrefix.userKeyById,String.valueOf(loginInfo.getId()));
        return R.success();
    }


    /**
     * 获取验证码图片
     * @param id
     * @param response
     * @throws IOException
     */
    @GetMapping("/getCodeImg")
    public void getCode(@RequestParam("id") String id, HttpServletResponse response) throws IOException {
        //设置不缓存图片
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "No-cache");
        response.setDateHeader("Expires", 0);
        //指定生成的响应图片
        response.setContentType("image/jpeg");
        VerifyUtil code = new VerifyUtil();
        BufferedImage image = code.getIdentifyImg();
        code.getG().dispose();
        //将图形验证码IO流传输至前端
        ImageIO.write(image, "JPEG", response.getOutputStream());
        System.out.println(code.getCode());
        redisService.set(UserPrefix.userVerifyCodeKey,id,code.getCode(),3000);
    }

    /**
     * 获取验证码文字
     * @param id
     * @return
     */
    @GetMapping("/getCode")
    public R getCode(@RequestParam("id") String id) {
        System.out.println("调用了获取验证码文字");
        return R.success((String)redisService.get(UserPrefix.userVerifyCodeKey,id));
    }

    /**
     * 更新头像/上传头像
     * @param request
     * @param file
     * @return
     */
    @PutMapping("/uploadhead")
    public R uploadHead(HttpServletRequest request,@RequestPart("file") MultipartFile file){
        System.out.println(file);
        LoginInfo loginInfo=jwtUtil.parseJwt(request.getHeader("token"));
        String address=ossService.upload(file);
        log.info("用户{}上传了头像，地址为{}",loginInfo.getId(),address);
        userService.uploadHead(loginInfo.getId(),address);
        return R.success(address);
    }

    /**
     * 放用户信息到redis中并生成token
     * @param user
     * @return
     */
    public String setToken(User user) {
//      创建token,返回token
        String token = jwtUtil.createJwt(new LoginInfo(user));
//      放入redis中
        redisService.set(UserPrefix.userKeyById, String.valueOf(user.getId()), token, 7 * 24 * 60 * 60 * 60);
//        生成的token
        log.info("生成的token:{}",token);
        return token;
    }

    /**
     * 获取用户基础信息
     * @param request
     * @return
     */
    @GetMapping("/info")
    public R getInfo(HttpServletRequest request){
        LoginInfo loginInfo=jwtUtil.parseJwt(request.getHeader("token"));
        LoginInfo response=userService.getInfo(loginInfo.getId());
        return R.success(response);
    }

    /**
     * todo 查看学生(有bug)
     * @param schoolName
     * @param username
     * @return
     */
    @GetMapping("/list/student")
    public R studentList(String schoolName,String username) {
        if(StringUtils.isEmpty(username))return R.error("学生名称不能为空");
        List<StudentDto> list=userService.studentList(schoolName,username);
        return R.success(list);
    }

    /**
     * 获取用户本月学习记录
     * @param request
     * @return
     */
    @GetMapping("/getStudyHistory")
    public R<List<StudyHistoryVO>> getStudyHistory(HttpServletRequest request){
        return userService.getStudyHistory(request);
    }

    /**
     * 获取用户的练习情况
     * @param request
     * @return
     */
    @GetMapping("/getPracticeDetail")
    public R<List<Practice>> getPracticeDetail(HttpServletRequest request){
        return userService.getPracticeDetail(request);
    }

    /**
     * 获取用户视频情况
     * @param request
     * @return
     */
    @GetMapping("/getVideoDetail")
    public R<List<TagVO>> getVideoDetail(HttpServletRequest request) {
        return userService.getVideoDetail(request);
    }

    /**
     * 上传文件
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public R upload(@RequestPart("file") MultipartFile file) {
        return R.success(ossService.upload(file));
    }

    /**
     * 家长身份认证接口
     * @param infoFormDTO
     * @return
     */
    @PostMapping("/submitRoleInfo")
    public R submitRoleInfo(@RequestBody InfoFormDTO infoFormDTO,HttpServletRequest request){
        return userService.submitRoleInfo(infoFormDTO,request);
    }

    /**
     * 查询家长的学生
     * @param request
     * @return
     */
    @GetMapping("/getMyStudentList")
    public R<List<StudentVO>> getMyStudentList(HttpServletRequest request) {
        return userService.getMyStudentList(request);
    }

    /**
     * 获取家长的学生最近7天观看的视频数量
     * @param id
     * @return
     */
    @GetMapping("/getRecentVideo")
    public R<List<Integer>> getRecentVideo(Long id) {
        return userService.getRecentVideo(id);
    }

    /**
     * 获取家长的学生近7天的练习数量
     * @param id
     * @return
     */
    @GetMapping("/getRecentPractice")
    public R<List<Integer>> getRecentPractice(Long id) {
        return userService.getRecentPractice(id);
    }

    /**
     * 提交用户反馈
     * @param content
     * @return
     */
    @PostMapping("/submitAdvice")
    public R submitAdvice(@RequestParam("content") String content) {
        if ( content.isEmpty() ) {
            return R.error("内容不能为空");
        }
        return userService.submitAdvice(content);
    }

    /**
     * 获取绘制饼状图所需数据 用户最近一周观看的视频详细信息
     * @param id
     * @return
     */
    @GetMapping("/getRecentVideoData")
    public R<List<PieVO>> getRecentVideoData(Long id) {
        return userService.getRecentVideoData(id);
    }

    /**
     * 获取绘制饼状图所需数据 用户最近一周完成的练习详细信息
     * @param id
     * @return
     */
    @GetMapping("/getRecentPracticeData")
    public R<List<PieVO>> getRecentPracticeData(Long id) {
        return userService.getRecentPracticeData(id);
    }

    /**
     * 由于前端localstorage存储的token是永久有效的 除非手动移除否则一直存在 因此需要提供接口判断token是否有效
     * @param request
     * @return
     */
    @GetMapping("/checkToken")
    public R checkToken(HttpServletRequest request) {
        LoginInfo info = jwtUtil.parseJwt(request.getHeader("token"));
        if (Objects.isNull(info)) {
            return R.success(null);
        }
        return R.success(info);
    }

    /**
     * 根据用户id查询用户信息
     * @param id
     * @return
     */
    @GetMapping("/getUserInfoById")
    public R<User> getUserInfoById(@RequestParam Long id) {
        return R.success(userService.getById(id));
    }
}
